#!/usr/bin/python3
# -*- coding: utf-8 -*
"""
Description: Table parser.
Class: TableParser.
"""
import re
from pygrok import Grok

from ..libs.log import LOGGER
from . import Parser


class TableParser(Parser):
    """
    Class TableParser is the parser that parses the table data to the formatted data.
    """

    def parse_content(self, key, content):
        """
        Parse the table data to formatted data.

        Args:
            key (str): the main key of the content.
            content (str): raw data.

        Returns:
            dict: parsed content.
            bool: parse succeed or fail.
        """
        # remove the blank line
        content = self.get_valid_lines(content)

        if len(content) == 0:
            LOGGER.warning("'%s' has no content.", key)
            return {}, True
        if len(content) == 1:
            LOGGER.warning("'%s' is an abnormal file.", key)
            return content, False

        file_type = self.param_config['log_type'][0]
        head = content[0]
        second = content[1]
        custom_file = self.regex_config.get('custom_file')

        if 'matched_grok' not in self.param_config.keys():
            old_grok, old_pattern = self.get_matched_pattern(key, head)

            if old_pattern is None:
                old_grok, old_pattern = self.find_matched_pattern_by_type(head, file_type,
                                                                          second)
                if old_grok is None:
                    LOGGER.error(
                        "No matched pattern for '%s', return raw content.", key)
                    return content, None, False
            matched_pattern = self.rename_pattern(head, old_grok, old_pattern)
            matched_grok = Grok(matched_pattern, custom_file)
            self.param_config['matched_grok'] = matched_grok
            self.param_config['matched_pattern'] = matched_pattern

        matched_grok = self.param_config.get('matched_grok')
        matched_pattern = self.param_config.get('matched_pattern')

        res, success = self.parse_table(content, matched_grok)

        return res, success

    @staticmethod
    def rename_pattern(head, old_grok, old_pattern):
        """
        Rename the name in the regex pattern using header.

        Args:
            head (str): header of the table.
            old_grok (grok object): related grok pattern that has been compiled.
            old_pattern (str): the matched old pattern.

        Returns:
            str: renamed pattern.
        """

        header = list(old_grok.match(head).values())
        index = 0
        new_pattern = old_pattern

        for match in re.finditer(r':(\w+)\}', old_pattern):
            substr = match.group(1)
            # remove symbol for the name of regex can only be \w.
            tmp_header = re.sub(r'[\]\)%#]', '', header[index].strip())
            tmp_header = re.sub(r'[^\w]', '_', tmp_header)
            tmp_header = tmp_header.lower()
            # name cannot start with digit
            if tmp_header != '' and tmp_header[0].isdigit():
                tmp_header = '_' + tmp_header
            new_pattern = new_pattern.replace(substr, tmp_header, 1)
            index += 1

        return new_pattern

    @staticmethod
    def parse_table(content, matched_grok):
        """
        Parse table content.

        Args:
            key (str)
            content (list)
            matched_pattern (str): the matched pattern.
            matched_grok (grok object): related grok pattern that has been compiled.

        Returns:
            dict: formatted data.
        """
        log_formated = []
        success = True

        for line in content[1:]:
            line_format = matched_grok.match(line)
            if line_format is None or line_format == {}:
                continue
            log_formated.append(line_format)

        return log_formated, success

    @staticmethod
    def get_valid_lines(lines):
        """
        remove line which starts with '---' or '===' or '***' or has no content.

        Args:
            lines (list): content to be detected.

        Returns:
            list: result after validating.
        """
        res = []
        for line in lines:
            if line.startswith('---') or line.startswith('==='):
                continue
            if line.startswith('***') or line.strip() == "":
                continue
            res.append(line.strip())

        return res


def get_class():
    """
    get TableParser class.

    Args:

    Returns:
        class
    """
    return TableParser
